﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web.Security;

namespace NStore.Domain
{
    public class User : MembershipUser
    {
        private int _id;
        public int Id
        {
            get { return _id; }
        }

        private string _passwordSalt;
        public string PasswordSalt
        {
            get { return _passwordSalt; }
        }

        private string _password;
        public string Password
        {
            get { return _password; }
        }

        private readonly string _userName;
        public override string UserName
        {
            get { return _userName; }
        }

        private ICollection<string> _roles = new HashSet<string>();
        public ICollection<string> Roles
        {
            get { return _roles; }
            set { _roles = value; }
        }

        protected User() {}

        public User(string username, string password)
        {
            _userName = username;
            _passwordSalt = GenerateSalt();
            _password = EncodePassword(password, PasswordSalt);
        }

        public virtual bool ValidatePassword(string password)
        {
            return _password.Equals(EncodePassword(password, PasswordSalt));
        }

        public override bool ChangePassword(string oldPassword, string newPassword)
        {
            if (EncodePassword(oldPassword, PasswordSalt) == Password)
            {
                _passwordSalt = GenerateSalt();
                _password = EncodePassword(newPassword, PasswordSalt);
                return true;
            }
            return false;
        }

        #region "Private methods"
        private const int SaltSizeInBytes = 16;
        
        protected internal string GenerateSalt()
        {
            byte[] buffer = new byte[SaltSizeInBytes];
            (new RNGCryptoServiceProvider()).GetBytes(buffer);
            return Convert.ToBase64String(buffer);
        }

        protected internal string EncodePassword(string pass, string salt)
        {
            byte[] bIn = Encoding.Unicode.GetBytes(pass);
            byte[] bSalt = Convert.FromBase64String(salt);
            byte[] bAll = new byte[bSalt.Length + bIn.Length];

            Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
            Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
            HashAlgorithm s = HashAlgorithm.Create("SHA1");

            return Convert.ToBase64String(s.ComputeHash(bAll));
        }
        #endregion
        
    }
}
